﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Microsoft.DirectX.DirectInput;

namespace KGE.Define
{
    [Serializable]
    public class Character
    {

        [Serializable]
        public class Action
        {
            [Serializable]
            public class Frame
            {
                public double Length;
                public Color FilterColor;
                public Rectangle DrawRectangle;

                public ObjectIndexer KImageIndexer;
                public ObjectIndexer KSoundIndexer;
            }

            public string Name;
            public Guid GUID;
            public string Version;
            public DateTime CreateTime;

            public Rectangle DrawRectangle;
            public double Length
            {
                get
                {
                    double l = 0.0;
                    foreach (Frame f in Frames)
                    {
                        l += f.Length;
                    }
                    return l;
                }
            }
            public List<Frame> Frames = new List<Frame>();
            public bool IsLoop = false;

            public Action(string name)
            {
                Name = name;
                GUID = Guid.NewGuid();
                CreateTime = DateTime.Now;
            }
        }

        intQueue actionQueue = new intQueue();

        const int Nothing1 = 0;
        const int Nothing2 = 1;
        const int Walking = 2;
        const int Running = 3;

        const int Attack1 = 4;
        const int Attack2 = 5;
        const int Attack3 = 6;
        const int Attack4 = 7; 
        
        const int Jump = 8;
        const int Provoking = 9;

        const int Hit = 0;
        List<KImagePackage> avatars = new List<KImagePackage>();
        //List<ObjectIndexer> avatarKIPNames = new List<ObjectIndexer>();
        List<Action> actions = new List<Action>();

        Util.HDTimer timer = new Util.HDTimer();
        Point AvatarOPoint;
        [NonSerialized]
        public Point Location;
        public int MoveSpeed = 2;
        public Direction Direction;
        double frameLength = 0;
        double actionLength = 0;
        int frameIndex = 0;
        int actionIndex = 0;
        bool isFaceToLeft = false;

        //public Point Location
        //{
        //    get
        //    {
        //        Point p = Location;

        //        p.X -= AvatarOPoint.X;
        //        p.Y -= AvatarOPoint.Y;

        //        if (isFaceToLeft)
        //        {
        //            p.X = -p.X;
        //            p.X -= Image.Size.Width;
        //        }
        //        Rectangle rect = new Rectangle(p, Image.Size);
        //        return rect;
        //    }
        //}

        bool IsLoop
        {
            get
            {
                return actions[actionIndex].IsLoop;
            }
        }
        bool IsFinish
        {
            get
            {
                if (!IsLoop)
                {
                    if (frameIndex == actions[actionIndex].Frames.Count - 1)
                    {
                        if (frameLength >= actions[actionIndex].Frames[frameIndex].Length)
                        {
                            return true;
                        }
                    }
                }
                return false;
            }
        }

        bool CanCombo(int aIndex, double time)
        {
            if (actionLength < time)
            {
                return true;
            }
            return false;
        }

        public bool IsWalking
        {
            get
            {
                if (actionIndex == Walking)
                {
                    return true;
                }
                return false;
            }
        }
        public bool IsRunning
        {
            get
            {
                if (actionIndex == Running)
                {
                    return true;
                }
                return false;
            }
        }
        public bool IsMoving
        {
            get
            {
                if (actionIndex == Walking || actionIndex == Running)
                {
                    return true;
                }
                return false;
            }
        }
        public bool IsNothing
        {
            get
            {
                if (actionIndex == Nothing1 || actionIndex == Nothing2)
                {
                    return true;
                }
                return false;
            }
        }
        public bool CanAction
        {
            get
            {
                if (IsNothing || IsMoving)
                {
                    return true;
                }
                return false;
            }
        }

        public void TurnLeft()
        {
            isFaceToLeft = true;
        }
        public void TurnRight()
        {
            isFaceToLeft = false;
        }

        public void MoveUp()
        {
            if (actionIndex > Running)
            {
                return;
            }
            int x = 1;
            if (actionIndex == Walking)
            {
                x = 1;
                DoWalking();
            }
            else if (actionIndex == Running)
            {
                x = 2;
                DoRunning();
            }
            Location.Y -= MoveSpeed * x;
        }
        public void MoveDown()
        {
            if (actionIndex > Running)
            {
                return;
            }
            int x = 1;
            if (actionIndex == Walking)
            {
                x = 1;
                DoWalking();
            }
            else if (actionIndex == Running)
            {
                x = 2;
                DoRunning();
            }
            Location.Y += MoveSpeed * x;
        }
        public void MoveLeft()
        {
            if (actionIndex > Running)
            {
                return;
            }
            int x = 1;
            if (actionIndex == Walking)
            {
                x = 1;
                DoWalking();
            }
            else if (actionIndex == Running)
            {
                x = 2;
                DoRunning();
            }
            TurnLeft();
            Location.X -= MoveSpeed * x;
        }
        public void MoveRight()
        {
            if (actionIndex > Running)
            {
                return;
            }
            int x = 1;
            if (actionIndex == Walking)
            {
                x = 1;
                DoWalking();
            }
            else if (actionIndex == Running)
            {
                x = 2;
                DoRunning();
            }
            TurnRight();
            Location.X += MoveSpeed * x;
        }

        public void DoNothing1()
        {
            if (IsLoop)
            {
                actionIndex = Nothing1;
                timer.Reset();
            }
            else
            {
                if (IsFinish)
                {
                    actionIndex = Nothing1;
                    timer.Reset();
                }
            }
        }
        public void DoNothing2()
        {
            actionIndex = Nothing2;
        }       

        public void DoWalking()
        {
            if (actionIndex > Running)
            {
                return;
            }
            if (!IsWalking)
            {
                actionIndex = Walking;
                timer.Reset();
            }
        }
        public void DoRunning()
        {
            if (actionIndex > Running)
            {
                return;
            }
            if (!IsRunning)
            {
                actionIndex = Running;
                timer.Reset();
            }
        }
        public void DoAttack()
        {
            if (CanAction)
            {
                frameIndex = 0;
                actionIndex = Attack1;
                timer.Reset();
            }
            else if (actionIndex == Attack1)
            {
                actionQueue.EnqueueCheckLast(Attack2);
            }
            else if (actionIndex == Attack2)
            {
                actionQueue.EnqueueCheckLast(Attack3);
            }
            else if (actionIndex == Attack3)
            {
                actionQueue.EnqueueCheckLast(Attack4);
            }
        }

        public void LoadAvatar(string fileName,Game g)
        {
            KImagePackage kip = (KImagePackage)Util.LoadObject(fileName);
            for (int i = 0; i < kip.Count; i++)
            {
                kip[i].Texture = g.Devices.GPU.KImage2Texture(kip[i]);
            }
            avatars.Add(kip);
            //AvatarKIPNames.Add(new ObjectIndexer(kipName));
        }
        public void LoadActions(string fileName)
        {
            actions.Add((Action)Util.LoadObject(fileName));
        }

        string filterFirstKey(string str)
        {
            if (str.StartsWith("up"))
            {
                int p = str.IndexOf(",");
                str = str.Substring(p + 1);
            }
            return str;
        }
        string getLastKey(string str)
        {
            int p = str.LastIndexOf(",");
            if (p > 0)
            {
                str = str.Substring(p + 1);
            }
            return str;
        }
        public void Heartbeat()
        {
            if (frameIndex >= actions[actionIndex].Frames.Count)
            {
                frameIndex = 0;
            }
            timer.Record();
            frameLength = timer.Seconds;
            if (frameLength >= actions[actionIndex].Frames[frameIndex].Length)
            {
                frameIndex++;
                if (frameIndex > actions[actionIndex].Frames.Count - 1)
                {
                    frameIndex = 0;
                    if (actions[actionIndex].IsLoop)
                    {

                    }
                    else
                    {
                        if (actionQueue.Count > 0)
                        {
                            actionIndex = actionQueue.Dequeue();
                        }
                        else
                        {
                            DoNothing2();
                        }
                    }
                }
                timer.Reset();
            } 
        }

        //public int ActionIndex
        //{
        //    get
        //    {
        //        return actions[actionIndex].Frames[frameIndex].KImageIndexer.Index;
        //    }
        //}
        public KImage[] Avatar
        {
            get
            {
                KImage[] avatar = new KImage[avatars.Count];
                for (int i = 0; i < avatar.Length; i++)
                {
                    avatar[i] = avatars[i][actions[actionIndex].Frames[frameIndex].KImageIndexer.Index];
                    avatar[i].OPoint = AvatarOPoint;
                    if (isFaceToLeft)
                    {
                        avatar[i].FlipToLeft();
                    }
                    else
                    {
                        avatar[i].FlipToRight();
                    }
                }
                return avatar;
            }
        } 

        public Character()
        {
            AvatarOPoint = new Point(245, 338);
            Location = new Point(320, 240);
        }
    }
}
